3.3.4 双向数据绑定原理

1.实现数据绑定的做法有大致如下几种:

  • 发布者-订阅者模式(backbone.js)
  • 脏值检查(angular.js)
  • 数据劫持(vue.js)

1.1发布者-订阅者模式

使用自定义的data属性在HTML代码中指明绑定。所有绑定起来的JavaScript对象以及DOM元素都将“订阅”一个发布者对象。
任何时候如果JavaScript对象或者一个HTML输入字段被侦测到发生了变化,我们将代理事件到发布者-订阅者模式,
这会反过来将变化广播并传播到所有绑定的对象和元素。

1.2脏值检查

angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,

最简单的方式就是通过 setInterval() 定时轮询检测数据变动,angular只有在指定的事件触发时进入脏值检测,大致如下:

  • DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
  • XHR响应事件 ( $http )
  • 浏览器Location变更事件 ( $location )
  • Timer事件( $timeout , $interval )
  • 执行 $digest() 或 $apply()

1.3数据劫持

通过 Object.defineProperty() 来劫持各个属性的 setter,getter,
在数据变动时发布消息给订阅者,触发相应的监听回调。

用原生js的 Object.defineProperty() 写一个双向数据绑定

  • 用原生Javascript对象中的访问器属性实现双向数据绑定
var input = document.querySelector("#text");
var data = {};
Object.defineProperty(data, "name", {
  configurable: true,
  get: function(){
      return input.value
  },
  set: function(newValue){
    //this.value = newValue;
    input.value = newValue;
  }
})
data.name = "sss";
input.onchange = function(){
  data.name = data.name;
}

作者:darr250
链接:https://www.jianshu.com/p/e8df6e3f6e34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Object.defineProperty缺陷的:

  • 1.只能对属性进行数据劫持,并且需要深度遍历整个对象
  • 2.对于数组不能监听数据的变化

proxy原生

  • 而proxy原生支持监听数组的变化,并且可以直接对整个对象进行拦截,

所有Vue在下个版本中用proxy替换object.defineProperty

vue 就地复用原则 | :key 原理 | vue1.x 的 track-by 的理解?

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。
如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,
而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

这个类似 Vue 1.x 的 track-by="$index" 。

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。

建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升

key: key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。
如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。
使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

参考